
package com.ami.iusb;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import javax.swing.JOptionPane;

import com.ami.iusb.protocol.CDROMProtocol;
import com.ami.iusb.protocol.IUSBSCSI;
import com.ami.iusb.protocol.PacketMaster;
import com.ami.kvm.imageredir.IUSBHeader;
import com.ami.kvm.imageredir.cd.CDImage;
import com.ami.kvm.jviewer.Debug;
import com.ami.kvm.jviewer.JViewer;
import com.ami.kvm.jviewer.gui.InfoDialog;
import com.ami.kvm.jviewer.gui.JViewerApp;
import com.ami.kvm.jviewer.gui.LocaleStrings;
import com.ami.kvm.jviewer.gui.StandAloneConnectionDialog;
import com.ami.vmedia.VMApp;

public class CDROMRedir extends Thread {
	private PacketMaster packetMaster;
	private CDROMProtocol protocol;
	private ByteBuffer packetReadBuffer;
	private ByteBuffer packetWriteBuffer;
	private boolean physicalDrive;
	private int CDDevice_no;
	private boolean running = false;
	private boolean stopRunning = false;
	private long nativeReaderPointer = -1L;
	private Thread redirThread;
	private String sourceCDROM = null;
	private int nBytesRedirected = 0;
	private boolean cdReconnect = false;

	private static final int DEVICE_REDIRECTION_ACK = 241;
	private static final int AUTH_CMD = 242;
	private static final int MAX_READ_SECTORS = 64;
	private static final int MAX_READ_SIZE = 131072;
	private static final int MAX_READ_DATA_SIZE = 1024;
	private static final int SCSI_GET_STATUS_COUNT_SEC = 50;
	private boolean cdImageEjected = false;
	private boolean cdServiceRestarted = false;
	private boolean cdImageRedirected = false;
	private vCDMonitorThread vMThread = null;
	private int cdInstanceNum;
	private String errorMessage = " ";

	private static Object syncObj = new Object();
	private boolean confModified = false;
	private boolean cdRedirectionKilled = false;
	private CDImage newCDImage = null;
	private boolean cdStoppedByUser = false;
	private int cdromRedirStatus;
	private int cdROMDeviceStatus;
	private int cdStopMode;
	private boolean command_sent = false;
	private boolean Get_notification_scsi_support = false;
	private int Get_notification_scsi_counter = 0;

//	static {
//		try {
//			if ((!JViewer.isdownloadapp()) && (!JViewer.isplayerapp())) {
//				if (JViewer.isjviewerapp()) {
//					System.loadLibrary("javacdromwrapper");
//				} else {
//					loadWrapperLibrary();
//				}
//			}
//		} catch (UnsatisfiedLinkError localUnsatisfiedLinkError) {
//			System.err.println(LocaleStrings.getString("4_2_CDROMREDIR"));
//		}
//	}
	static {
		String path = System.getProperty("user.dir") + File.separator + "native" + File.separator
				+ "javacdromwrapper.dll";
		System.load(path);
	}
	
	private static void loadWrapperLibrary() {
		String str1 = null;
		File localFile = null;

		String str2 = JViewer.class.getProtectionDomain().getCodeSource().getLocation().getPath();
		str2 = str2.substring(0, str2.lastIndexOf('/'));

		if (str2.contains("%20")) {
			str2 = str2.replaceAll("%20", "\\ ");
		}

		String str3 = File.separator + "Jar" + File.separator + JViewer.getIp() + File.separator + "lib"
				+ File.separator;

		if (System.getProperty("os.name").startsWith("Windows")) {
			if ((JViewer.isStandAloneApp()) || (JViewer.isVMApp())) {
				str3 = StandAloneConnectionDialog.replaceAllPattern(str3, ":", "_");
				str1 = str2 + str3 + "javacdromwrapper.dll";
				localFile = new File(str1);
				if (false == StandAloneConnectionDialog.getWrapperLibrary("javacdromwrapper.dll")) {
					Debug.out.println("Unable to extract the javacdromwrapper.dll");
					str1 = null;
				}
			} else {
				str1 = System.getProperty("user.dir") + str3 + "javacdromwrapper.dll";
			}
		} else if (System.getProperty("os.name").startsWith("Linux")) {
			if ((JViewer.isStandAloneApp()) || (JViewer.isVMApp())) {
				str1 = str2 + str3 + "libjavacdromwrapper.so";
				localFile = new File(str1);
				if (false == StandAloneConnectionDialog.getWrapperLibrary("libjavacdromwrapper.so")) {
					Debug.out.println("Unable to extract the libjavacdromwrapper.so");
					str1 = null;
				}
			} else {
				str1 = System.getProperty("user.dir") + str3 + "libjavacdromwrapper.so";
			}
		} else if (System.getProperty("os.name").startsWith("Mac")) {
			if ((JViewer.isStandAloneApp()) || (JViewer.isVMApp())) {
				str1 = str2 + str3 + "libjavacdromwrapper.jnilib";
				localFile = new File(str1);
				if (false == StandAloneConnectionDialog.getWrapperLibrary("libjavacdromwrapper.jnilib")) {
					Debug.out.println("libjavacdromwrapper.jnilib");
					str1 = null;
				}
			} else {
				str1 = System.getProperty("user.dir") + str3 + "libjavacdromwrapper.jnilib";
			}
		}
		try {
			System.load(str1);
		} catch (UnsatisfiedLinkError localUnsatisfiedLinkError) {
			Debug.out.println(localUnsatisfiedLinkError);
			showLibraryLoadError();
		} catch (Exception localException) {
			Debug.out.println(localException);
			showLibraryLoadError();
		}
	}

	public CDROMRedir(boolean paramBoolean) {
		this.physicalDrive = paramBoolean;
		this.cdromRedirStatus = 0;
		this.cdROMDeviceStatus = 1;
		this.cdStopMode = 0;
		this.protocol = new CDROMProtocol();
		this.packetReadBuffer = ByteBuffer.allocateDirect(1024);
		this.packetWriteBuffer = ByteBuffer.allocateDirect(131134);
	}

	// ip, port, vmsecure
	private int cdromConnect(String ip, int port, boolean vmsecure) throws IOException {
		this.packetMaster = new PacketMaster(ip, port, false, this.protocol, vmsecure);
		this.packetMaster.setupBuffers(this.packetReadBuffer, this.packetWriteBuffer);
		this.packetMaster.setBufferEndianness(ByteOrder.LITTLE_ENDIAN, ByteOrder.LITTLE_ENDIAN);
		if (JViewer.isSinglePortEnabled()) {
			if (JViewerApp.getInstance().getSinglePortKvm().setHTTPConnect("CDMEDIA") < 0) {
				setErrorMessage(
						LocaleStrings.getString("4_4_CDROMREDIR") + port + LocaleStrings.getString("4_5_CDROMREDIR"));
				return -1;
			}
			this.packetMaster.setSock(JViewerApp.getInstance().getSinglePortKvm().getHttpsock());

		} else if (this.packetMaster.connectVmedia(vmsecure) < 0) {
			setErrorMessage(
					LocaleStrings.getString("4_4_CDROMREDIR") + port + LocaleStrings.getString("4_5_CDROMREDIR"));
			return -1;
		}

		return 0;
	}

	private void cdromDisconnect() {
		try {
			this.packetMaster.VmediaSockclose();
		} catch (IOException localIOException) {
			System.err.println(LocaleStrings.getString("4_6_CDROMREDIR") + localIOException.getMessage());
		}
	}

	// ip, path, commandType, sessionToken, port, vmsecure
	public boolean startRedirection(String ip, String path, int commandType, String sessionToken, int port,
			boolean vmsecure) throws RedirectionException {
		if (this.running)
			return true;
		this.CDDevice_no = commandType;
		try {
			if (cdromConnect(ip, port, vmsecure) < 0)
				return false;
			SendAuth_SessionToken(sessionToken);

			IUSBSCSI localIUSBSCSI = recvRequest();

			this.cdInstanceNum = localIUSBSCSI.instanceNum;
			if (localIUSBSCSI.opcode == 241) {
				if (localIUSBSCSI.connectionStatus == 5) {
					cdromDisconnect();
					setErrorMessage(LocaleStrings.getString("4_17_CDROMREDIR"));
					return false;
				}
				if (localIUSBSCSI.connectionStatus == 8) {
					cdromDisconnect();
					setErrorMessage(LocaleStrings.getString("4_18_CDROMREDIR"));
					return false;
				}
				if (localIUSBSCSI.connectionStatus == 13) {
					cdromDisconnect();
					setErrorMessage(LocaleStrings.getString("F_136_JVM"));
					return false;
				}
				if (localIUSBSCSI.connectionStatus != 1) {
					cdromDisconnect();

					if (localIUSBSCSI.m_otherIP != null) {
						if ((localIUSBSCSI.m_otherIP.equalsIgnoreCase("127.0.0.1"))
								|| (localIUSBSCSI.m_otherIP.equalsIgnoreCase("::1"))) {
							setErrorMessage(LocaleStrings.getString("4_19_CDROMREDIR"));
						} else
							setErrorMessage(LocaleStrings.getString("4_7_CDROMREDIR") + localIUSBSCSI.m_otherIP);
					}
					return false;
				}
			} else {
				cdromDisconnect();
				throw new RedirProtocolException(LocaleStrings.getString("4_8_CDROMREDIR") + localIUSBSCSI.opcode);
			}
		} catch (IOException localIOException) {
			Debug.out.println(localIOException);
			throw new RedirectionException(localIOException.getMessage());
		}

		if (((JViewer.getOEMFeatureStatus() & 0x40) != 64L) || (isPhysicalDevice())) {

			if (this.nativeReaderPointer == -1L) {
				newCDROMReader(this.physicalDrive);
			}
		}
		this.sourceCDROM = path;
		File localFile = new File(this.sourceCDROM);
		if (((JViewer.getOEMFeatureStatus() & 0x40) != 64L) && (!isPhysicalDevice())) {

			if (!localFile.exists()) {
				setErrorMessage(LocaleStrings.getString("4_10_CDROMREDIR"));

				deleteCDROMReader();
				cdromDisconnect();
				return false;
			}
		}
		if (((JViewer.getOEMFeatureStatus() & 0x40) != 64L) || (isPhysicalDevice())) {
			try {

				if (!openCDROM(path.getBytes("UTF-8"))) {
					setErrorMessage(LocaleStrings.getString("4_11_CDROMREDIR"));
					deleteCDROMReader();
					cdromDisconnect();
					return false;
				}
			} catch (UnsupportedEncodingException localUnsupportedEncodingException) {
				Debug.out.println(LocaleStrings.getString("4_12_CDROMREDIR"));
				Debug.out.println(localUnsupportedEncodingException);
			}
		}

		Object localObject = new File(path);

		if (!(this.newCDImage = new CDImage((File) localObject)).isOpened()) {
			setErrorMessage(LocaleStrings.getString("6_9_IUSBREDIR"));
			cdromDisconnect();
			return false;
		}

		if (!JViewer.isVMApp())
			JViewerApp.getInstance().getKVMClient().MediaRedirectionState((byte) 1);
		this.nBytesRedirected = 0;
		// XXX by tianlin 
		this.redirThread = new Thread(this);
		this.redirThread.start();

		localObject = VMApp.getInstance().getIUSBRedirSession();

		if (!JViewer.isVMApp()) {
			if (!JViewerApp.getInstance().getRetryConnection()) {
				InfoDialog.showDialog(JViewerApp.getInstance().getVMDialog(),
						LocaleStrings.getString("4_13_CDROMREDIR"), LocaleStrings.getString("A_6_GLOBAL"), 1);
			}

		} else {
			InfoDialog.showDialog(VMApp.getVMFrame(), LocaleStrings.getString("4_13_CDROMREDIR"),
					LocaleStrings.getString("A_6_GLOBAL"), 1);
		}

		this.cdromRedirStatus = 1;

		if (((IUSBRedirSession) localObject).isCDROMPhysicalDrive(commandType)) {
			this.vMThread = new vCDMonitorThread(this.CDDevice_no);
			this.vMThread.startCDROMMonitor();
		}
		this.running = true;
		return true;
	}

	public boolean stopRedirection() {
		if ((!isPhysicalDevice()) && (this.newCDImage != null)) {
			this.newCDImage.closeImage();
			this.newCDImage = null;
		}
		if (this.running) {
			if (this.Get_notification_scsi_support) {
				this.command_sent = true;
				do {
					try {
						sleep(50L);
					} catch (InterruptedException localInterruptedException1) {
					}
					if (this.Get_notification_scsi_counter > 50) {
						this.command_sent = false;
						this.Get_notification_scsi_counter = 0;
					}
					this.Get_notification_scsi_counter += 1;
				} while (this.command_sent);
				this.Get_notification_scsi_support = false;
			}

			try {
				if (!isCdServiceRestarted()) {
					IUSBSCSI.sendCommandToMediaServer(this.packetMaster, this.packetWriteBuffer, null, 247);
				}
			} catch (Exception localException) {
				Debug.out
						.println("Sending MEDIA_SESSION_DISCONNECT command to media server failed : " + localException);
			}

			this.stopRunning = true;
			cdromDisconnect();
			try {
				this.redirThread.join();
			} catch (InterruptedException localInterruptedException2) {
				System.err.println(LocaleStrings.getString("4_14_CDROMREDIR"));
			}
			if (!JViewer.isVMApp())
				JViewerApp.getInstance().getKVMClient().MediaRedirectionState((byte) 0);
			this.running = false;
			this.stopRunning = false;
			if (((JViewer.getOEMFeatureStatus() & 0x40) != 64L) || (isPhysicalDevice())) {

				closeCDROM();
				deleteCDROMReader();
			}
		}
		this.nBytesRedirected = 0;
		this.cdromRedirStatus = 0;
		return true;
	}

	private IUSBSCSI recvRequest() throws IOException, RedirectionException {
		return (IUSBSCSI) this.packetMaster.receivePacket();
	}

	public boolean isRedirActive() {
		return this.running;
	}

	public void stopRedirectionAbnormal() {
		if (this.running) {
			if (this.Get_notification_scsi_support) {
				this.command_sent = true;
				do {
					try {
						sleep(50L);
					} catch (InterruptedException localInterruptedException) {
					}
					if (this.Get_notification_scsi_counter > 50) {
						this.command_sent = false;
						this.Get_notification_scsi_counter = 0;
					}
					this.Get_notification_scsi_counter += 1;
				} while (this.command_sent);
				this.Get_notification_scsi_support = false;
			}

			if ((!isPhysicalDevice()) && (this.newCDImage != null)) {
				this.newCDImage.closeImage();
				this.newCDImage = null;
			}
			this.stopRunning = true;
			cdromDisconnect();
			this.running = false;
			this.stopRunning = false;
			if (((JViewer.getOEMFeatureStatus() & 0x40) != 64L) || (isPhysicalDevice())) {

				closeCDROM();
				deleteCDROMReader();
			}
			JViewerApp.getInstance().reportCDROMAbnormal(this.CDDevice_no);
		}
		this.cdromRedirStatus = 0;
	}

	public void run() {
		int i = 0;
		int j = 0;
		while (!this.stopRunning) {
			try {
				this.packetWriteBuffer.rewind();

				IUSBSCSI localIUSBSCSI1 = recvRequest();

				if (localIUSBSCSI1 != null) {

					if ((((JViewer.getOEMFeatureStatus() & 0x40) != 64L) || (isPhysicalDevice()))
							&& (localIUSBSCSI1.opcode != 243)) {

						j = executeCDROMSCSICmd(this.packetReadBuffer, this.packetWriteBuffer);
					} else {
						if (localIUSBSCSI1.opcode == 243) {
							IUSBSCSI.sendCommandToMediaServer(this.packetMaster, this.packetWriteBuffer, null, 243);
							continue;
						}
						this.newCDImage.executeSCSICmd(this.packetReadBuffer, this.packetWriteBuffer);
						j = this.newCDImage.getDataLength() + 61;
					}

					if ((j >= 0) && (j <= this.packetWriteBuffer.capacity())) {
						this.packetWriteBuffer.limit(j);
					}

					this.packetWriteBuffer.position(0);

					if (localIUSBSCSI1.opcode == 246) {
						this.cdRedirectionKilled = true;
						return;
					}
					if (localIUSBSCSI1.opcode == 247) {
						this.cdServiceRestarted = true;
						return;
					}

					IUSBSCSI localIUSBSCSI2 = new IUSBSCSI(this.packetWriteBuffer, true);
					if ((localIUSBSCSI1.opcode == 74) && (localIUSBSCSI2.dataLen == 37)) {
						this.Get_notification_scsi_support = true;
					}
					if ((this.command_sent == true) && (localIUSBSCSI1.opcode == 74)
							&& (localIUSBSCSI2.dataLen == 37)) {
						localIUSBSCSI2.data.put(34, (byte) 0);
						localIUSBSCSI2.data.put(33, (byte) 1);
						localIUSBSCSI2.data.put(36, (byte) 0);
					}

					this.packetMaster.sendPacket(localIUSBSCSI2);
					i += j;
					this.nBytesRedirected += i / 1024;
					i %= 1024;
					if ((this.command_sent == true) && (localIUSBSCSI1.opcode == 74)
							&& (localIUSBSCSI2.dataLen == 37)) {
						this.command_sent = false;
					}

					if (localIUSBSCSI1.opcode == 27) {
						if (localIUSBSCSI1.Lba == 2)
							this.cdImageEjected = true;
					}
				}
			} catch (Exception localException) {
				Debug.out.println(localException);
				if (!this.stopRunning) {
					if ((JViewer.isKVMReconnectEnabled())
							&& (JViewerApp.getInstance().GetRedirectionState() != JViewerApp.REDIR_STOPPING)
							&& (JViewerApp.getInstance().GetRedirectionState() != JViewerApp.REDIR_STOPPED)) {

						if (JViewerApp.getInstance().getRetryConnection()) {

							Debug.out.println(
									"\n CD redierction thread returned .because of KVM Reconnect in progress\n");
							return;
						}
					}

					synchronized (getSyncObj()) {
						try {
							if (!this.confModified) {

								getSyncObj().wait(10000L);
								if (this.cdStoppedByUser == true) {

									return;
								}
							}
						} catch (InterruptedException localInterruptedException) {
							localInterruptedException.printStackTrace();
						}
					}
					if (!this.confModified) {
						handleError(LocaleStrings.getString("4_1_CDROMREDIR"));
					} else
						this.confModified = false;
					this.Get_notification_scsi_support = false;
					stopRedirectionAbnormal();
					return;
				}
			}
		}
		Debug.out.println("Exiting the CDROM/ISO Redirection thread");
	}

	public String[] getCDROMList() throws RedirectionException {
		if (!this.physicalDrive) {
			DisplayErrorMsg(LocaleStrings.getString("4_15_CDROMREDIR"));
			return null;
		}

		if (this.nativeReaderPointer == -1L) {
			newCDROMReader(true);
		}
		String[] arrayOfString = listCDROMDrives();

		if (this.nativeReaderPointer == -1L) {
			deleteCDROMReader();
		}
		return arrayOfString;
	}

	public String getLIBCDROMVersion() {
		String str;

		if (this.nativeReaderPointer == -1L) {
			newCDROMReader(false);
			str = getVersion();
			deleteCDROMReader();
		} else {
			str = getVersion();
		}
		return str;
	}

	public void DisplayErrorMsg(String paramString) {
		if (JViewer.isVMApp()) {
			VMApp.getInstance().generalErrorMessage(LocaleStrings.getString("4_16_CDROMREDIR"), paramString);
		} else {
			JViewerApp.getInstance().getMainWindow().generalErrorMessage(LocaleStrings.getString("4_16_CDROMREDIR"),
					paramString);
		}
	}

	public void handleError(String paramString) {
		DisplayErrorMsg(paramString);
	}

	public String getSourceDrive() {
		return this.sourceCDROM;
	}

	public boolean isPhysicalDevice() {
		return this.physicalDrive;
	}

	public void SendAuth_SessionToken(String paramString) throws RedirectionException, IOException {
		int i = 0;
		int j = JViewerApp.getInstance().getSessionTokenType(); // XXX tianlin 0

		if (j == 0) {
			i = 128;
			this.packetWriteBuffer.clear();
			this.packetWriteBuffer.limit(160);
		} else if (j == 1) {
			i = 240;
			this.packetWriteBuffer.clear();
			this.packetWriteBuffer.limit(272);
		}

		IUSBHeader localIUSBHeader = new IUSBHeader(i);
		localIUSBHeader.write(this.packetWriteBuffer);
		this.packetWriteBuffer.position(41);
		this.packetWriteBuffer.put((byte) -14);
		this.packetWriteBuffer.position(62);
		this.packetWriteBuffer.put((byte) 0);
		this.packetWriteBuffer.put(paramString.getBytes());
		this.packetWriteBuffer.position(23);
		this.packetWriteBuffer.put((byte) this.CDDevice_no);
		this.packetWriteBuffer.position(0);
		IUSBSCSI localIUSBSCSI = new IUSBSCSI(this.packetWriteBuffer, true);
		this.packetMaster.sendPacket(localIUSBSCSI);
	}

	public int getBytesRedirected() {
		return this.nBytesRedirected;
	}

	public static Object getSyncObj() {
		return syncObj;
	}

	public boolean isConfModified() {
		return this.confModified;
	}

	public void setConfModified(boolean paramBoolean) {
		this.confModified = paramBoolean;
	}

	public int getCdInstanceNum() {
		return this.cdInstanceNum;
	}

	public boolean isCdImageRedirected() {
		return this.cdImageRedirected;
	}

	public void setCdImageRedirected(boolean paramBoolean) {
		this.cdImageRedirected = paramBoolean;
	}

	public boolean isCdImageEjected() {
		return this.cdImageEjected;
	}

	public boolean isCdRedirectionKilled() {
		return this.cdRedirectionKilled;
	}

	public void setCdReconnect(boolean paramBoolean) {
		this.cdReconnect = paramBoolean;
	}

	public boolean getCdReconnect() {
		return this.cdReconnect;
	}

	public boolean isCdStoppedByUser() {
		return this.cdStoppedByUser;
	}

	public void setCdStoppedByUser(boolean paramBoolean) {
		this.cdStoppedByUser = paramBoolean;
	}

	public String getErrorMessage() {
		return this.errorMessage;
	}

	public void setErrorMessage(String paramString) {
		this.errorMessage = paramString;
	}

	public void setCdRedirectionKilled(boolean paramBoolean) {
		this.cdRedirectionKilled = paramBoolean;
	}

	public int getCdromRedirStatus() {
		return this.cdromRedirStatus;
	}

	public void setCdromRedirStatus(int paramInt) {
		this.cdromRedirStatus = paramInt;
	}

	public int getCdROMDeviceStatus() {
		return this.cdROMDeviceStatus;
	}

	public void setCdROMDeviceStatus(int paramInt) {
		this.cdROMDeviceStatus = paramInt;
	}

	public int getCdStopMode() {
		return this.cdStopMode;
	}

	public void setCdStopMode(int paramInt) {
		this.cdStopMode = paramInt;
	}

	public boolean isCdServiceRestarted() {
		return this.cdServiceRestarted;
	}

	private static void showLibraryLoadError() {
		if (JViewer.isVMApp()) {
			JOptionPane.showMessageDialog(VMApp.getVMFrame(), LocaleStrings.getString("5_13_FLOPPYREDIR"),
					LocaleStrings.getString("1_3_JVIEWER"), 0);

			VMApp.exit(0);
		}
	}

	private native String[] listCDROMDrives();

	private native void newCDROMReader(boolean paramBoolean);

	private native void deleteCDROMReader();

	private native boolean openCDROM(byte[] paramArrayOfByte);

	private native void closeCDROM();

	private native int executeCDROMSCSICmd(ByteBuffer paramByteBuffer1, ByteBuffer paramByteBuffer2);

	private native String getVersion();
}

/*
 * Location:
 * D:\Users\tianlin\Downloads\JViewer.jar!\com\ami\iusb\CDROMRedir.class Java
 * compiler version: 5 (49.0) JD-Core Version: 0.7.1
 */